package ru.spb.osll.myfit.client.widget;

import java.util.Vector;

import ru.spb.osll.myfit.client.PageMode;
import ru.spb.osll.myfit.common.PageElementType;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableCell;
import ru.spb.osll.myfit.common.TableCellResult;
import ru.spb.osll.myfit.common.TableStyle;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.TextBox;

public abstract class TableWidget extends PageElementWidget{//extends FlexTable  implements PageElementWidget {

	protected int m_selectedRow = -1;
	protected MyFlexTable m_flexTable;// = new FlexTable();
	protected int m_currentCell;
	private TableStyle m_tableStyle;

	protected MenuItem m_deleteRowItem;
	protected MenuItem m_addRowItem;
//	protected MenuItem m_deleteCellItem;
	protected MenuItem m_addCellItem;

	/**
	 * Mode: edit/view
	 */
	private PageMode mode = PageMode.EDIT;

	abstract protected void addRow(int row, Vector<TableCell> data);

	abstract protected void addNewRow(int row);
	
	abstract protected void addNewCell(int row, int cell);
	
	abstract protected void deleteCell(int row, int cell);

	abstract protected void changeWidth(TextBox tb, int displace);

	abstract protected void refreshTable(FlexTable table);

	abstract protected void setReadOnly(boolean isReadOnly);

	abstract protected void tuneMenu();


	Command deleteRowCommand = new Command() {
		public void execute() {
		  m_rootPopupMenu.hide();
			if (m_selectedRow >= 0)
				m_flexTable.removeRow(m_selectedRow);
			if (m_flexTable.getRowCount() == 0) {
				removeFromParent();
				try {
					this.finalize();
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	};

	Command addRowCommand = new Command() {
		public void execute() {
			m_rootPopupMenu.hide();
			if (m_selectedRow >= 0)
				addNewRow(m_selectedRow + 1);
		}
	};

	Command deleteCellCommand = new Command() {
		public void execute() {
			m_rootPopupMenu.hide();
			if (m_selectedRow >= 0 && m_currentCell >= 0){
				deleteCell(m_selectedRow, m_currentCell);
			}
		}
	};

	Command addCellCommand = new Command() {
		public void execute() {
			m_rootPopupMenu.hide();
			if (m_selectedRow > 0 && m_currentCell >= 0){
				addNewCell(m_selectedRow, m_currentCell + 1);
			}
		}
	};

	public TableWidget(GWTWidgetFactory gwtWidgetFactory, Table table) {
	 super(gwtWidgetFactory);
	 
	 sinkEvents(Event.ONMOUSEUP | Event.ONDBLCLICK | Event.ONCONTEXTMENU);
	 createPopupMenu();
	 addCustomItemInMenu();

	 setTableStyle(table.getStyle());
	  m_flexTable = m_gwtWidgetFactory.createMyFlexTable();
	 
		m_flexTable.setCellSpacing(0);
		m_flexTable.setCellPadding(0);

		m_flexTable.setStyleName("flexTableStyle");

		insertTable(table);
		Vector<Vector<TableCell>> data = table.getData();

		for (int i = 0; i < data.size(); ++i) {
			Vector<String> line = new Vector<String>();
			Vector<TableCell> cellLine = data.elementAt(i);
			for (int j = 0; j < cellLine.size(); j++)
				line.add(cellLine.get(j).getText());
			addRow(i, cellLine);
		}
		initWidget(m_flexTable);
	    
	}
	
	private void addCustomItemInMenu(){
	  m_rootMenuBar.addSeparator();
	  
	  m_deleteRowItem = m_gwtWidgetFactory.createMenuItem("Delete row", true, deleteRowCommand);
	  m_addRowItem = m_gwtWidgetFactory.createMenuItem("Add row", true, addRowCommand);
	  m_addCellItem = m_gwtWidgetFactory.createMenuItem("Add cell", true, addCellCommand);

	  m_rootMenuBar.addItem(m_deleteRowItem);
	  m_rootMenuBar.addItem(m_addRowItem);
	  m_rootMenuBar.addItem(m_addCellItem);
	}

	protected TextBox createTextEdit(TableCell cell) {
		TextBox tb = new TextBox();

		String text = cell.getText();
		tb.setStyleName("tableCellStyle");
		if (cell.getTestResult().equals(TableCellResult.PASS))
			tb.setStyleName("tableCellPassStyle");
		else if (cell.getTestResult().equals(TableCellResult.FAIL))
			tb.setStyleName("tableCellFailStyle");
		else if (cell.getTestResult().equals(TableCellResult.EXCEPTION)) {
			tb.setStyleName("tableCellExecptionStyle");
			Tooltip tooltip = new Tooltip(cell.getTooltip());
			tb.addMouseListener(new TooltipMouseListener(tooltip));
		}

		int length = (text.trim()).length();
		int normLen = (length > 0) ? length : 1;
		tb.setVisibleLength(normLen);
		tb.setText(text.trim());

		tb.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_ESCAPE) {
					TextBox tb = (TextBox) event.getSource();
					HorizontalPanel parent = (HorizontalPanel) tb.getParent();
					tb.removeFromParent();
					if (parent.getWidgetCount() == 0)
						refreshTable((FlexTable) parent.getParent());
				} else if (event.getCharCode() == KeyCodes.KEY_BACKSPACE
						|| event.getCharCode() == KeyCodes.KEY_DELETE)
					changeWidth((TextBox) event.getSource(), -1);
				else if (event.getCharCode() > 47 || event.getCharCode() == 32)
					changeWidth(((TextBox) event.getSource()), 1);
			}
		});

		tb.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
			 m_currentCell =  m_flexTable.getCellForEvent(event).getCellIndex();
			 m_selectedRow =  m_flexTable.getCellForEvent(event).getRowIndex();
			}
		});

		tb.addKeyUpHandler(new KeyUpHandler() {
			@Override
			public void onKeyUp(KeyUpEvent event) {
				changeWidth(((TextBox) event.getSource()), 0);
			}
		});

		return tb;
	}


	protected void onRightClick(Event event) {
		if (!(PageMode.EDIT).equals(mode))
			return;
		 Element td = m_flexTable.getEventTargetCell(event);
		if (td == null) {
			m_selectedRow = -1;
		}
			
		m_currentCell = td.getChildCount();
		Element tr = DOM.getParent(td);
		Element body = DOM.getParent(tr);
		m_selectedRow = DOM.getChildIndex(body, tr);
		m_currentCell = DOM.getChildIndex(tr, td);
		GWT.log("selectedRow " + m_selectedRow);
		event.stopPropagation();
		tuneMenu();
			
			//event.get
			
		  int x = event.getClientX(); 
		  int y = event.getClientY();
		  m_rootPopupMenu.setPopupPosition(x, y);
		  m_rootPopupMenu.show();
		 
	}

	public void onBrowserEvent(Event event) {
		GWT.log("onBrowserEvent", null);
		event.preventDefault();
		switch (DOM.eventGetType(event)) {
		case Event.ONMOUSEUP:
			if (DOM.eventGetButton(event) == Event.BUTTON_LEFT) {
				GWT.log("Event.BUTTON_LEFT", null);
			}

			if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
				GWT.log("Event.BUTTON_RIGHT", null);
				onRightClick(event);
			}
			break;

		case Event.ONDBLCLICK:
			break;

		case Event.ONCONTEXTMENU:
			GWT.log("Event.ONCONTEXTMENU", null);
			break;

		default:
			break;
		}
	}

	/**
	 * Disable / enable cells of the widgets
	 * 
	 * @param mode
	 */
	public void setMode(PageMode mode) {
		boolean isReadOnly = true;
		switch (mode) {
		case EDIT:
			this.mode = PageMode.EDIT;
			isReadOnly = false;
			break;
		case VIEW:
			this.mode = PageMode.VIEW;
			isReadOnly = true;
			break;
		}
		setReadOnly(isReadOnly);
	}

	public void setTableStyle(TableStyle tableStyle) {
		m_tableStyle = tableStyle;
	}

	public TableStyle getTableStyle() {
		return m_tableStyle;
	}
	
	@Override
	public void setOpen (boolean isOpen) {
    // no action needed.
  }
	
	public static class MyFlexTable extends FlexTable{
	  @Override
	  public Element getEventTargetCell(Event arg0) {
	    return super.getEventTargetCell(arg0);
	  }
	}
	
	public void insertTable(Table table) {
	  m_flexTable.removeAllRows();
	  setTableStyle(table.getStyle());	  
	  Vector<Vector<TableCell>> data = table.getData();

    for (int i = 0; i < data.size(); ++i) {
      Vector<String> line = new Vector<String>();
      Vector<TableCell> cellLine = data.elementAt(i);
      for (int j = 0; j < cellLine.size(); j++)
        line.add(cellLine.get(j).getText());
      addRow(i, cellLine);
    }
	}
	
	@Override
	public PageElementType getType() {
	  return PageElementType.TABLE;
	}

}
